#ifndef __MATRIX_INFORMATION_CLASS_DEFINE__
#define __MATRIX_INFORMATION_CLASS_DEFINE__
#pragma once
#include "framework.h"
#include "VectorInformation.h"
/*
----------------------------------------------------------------------------------------
    2.矩阵:可以单行单列,可以多行多列,（二维数组,也可以称为向量的数组）,只有一行的矩阵也可以称为行向量,只有一列的矩阵可以称为列向量
      矩阵中的数据表示可以用下标表示,行与列都从下标1开始。
        示例:A矩阵
              [01  83  15 90]
              [06  12  75 26]
              [31  71  61 59]
              [18  35  20 17]
              A矩阵中一行二列的数据是：83
              A矩阵中三行一列的数据是：31
----------------------------------------------------------------------------------------
    3.方阵:行数等于列数的矩阵就称为方阵
----------------------------------------------------------------------------------------
    4.对角矩阵：对角线元素不等于0且其它元素均为0的矩阵称为对角矩阵
            示例：
                [01  00  00 00]
                [00  12  00 00]
                [00  00  61 00]
                [00  00  00 17]
----------------------------------------------------------------------------------------
    5.单位矩阵：对角线元素等于1且其它元素均为0的矩阵称为单位矩阵
            示例：
                    [01  00  00]
            I1 =    [00  01  00]
                    [00  00  01]
----------------------------------------------------------------------------------------
    6.矩阵转置：指将矩阵行换成列或将列换成行

            [01  83  15 90]┯            [01  06  18]
            [06  12  75 26]        =         [83  12  35]
            [18  35  20 17]                [15  75  20]
                                        [90  26  17]
            a).矩阵转置再转置后等于原矩阵.(M┯)┯ = M
            b).对角矩阵转置后仍等于原对角矩阵.(D┯) = D
----------------------------------------------------------------------------------------
    7.标量与矩阵的乘法,即标量乘以矩阵中的每一个数值
                 [m11 m12 m13]        [km11 km12 km13]
                 [m21 m22 m23]        [km21 km22 km23]
        kM = K * [m31 m32 m33] =     [km31 km32 km33]
                 [m41 m42 m43]        [km41 km42 km43]
                 [m51 m52 m53]        [km51 km52 km53]
----------------------------------------------------------------------------------------
    8.矩阵之间的乘法:
        限制规则：
        1.第一个矩阵的列数必须和第二个矩阵的行数相等
        2.第一个矩阵的行数决定了结果的行数,第二个矩阵的列数决定了结果的列数

        推倒出的公式包含：
        AB≠BA
        (AB)C=A(BC)
        K(AB)=(KA)B=(KB)A
        (AB)┯=B┯A┯
        (M1M2M3...Mn)┯=Mn┯...M3┯M2┯M1┯

        A        *        B            =            AB
      [? ?]              [? ? ? ? ?]            [? ? ? ? ?]
      [? ?]              [? ? ? ? ?]            [? ? ? ? ?]
      [? ?]                                    [? ? ? ? ?]
      [? ?]                                    [? ? ? ? ?]
      A矩阵4行2列        B矩阵2行5列            AB结果为4行5列

      4*2                2*5                        4*5
      计算方式：第一个矩阵用行的值分别乘以第二个矩阵中列的每个值
               结果AB中的第一行第一个值：A的第一行乘以B的第一列,AB中的第一行第二个值：A的第一行乘以B的第二列,...
               结果AB中的第二行第一个值：A的第二行乘以B的第一列,AB中的第二行第二个值：A的第二行乘以B的第二列,...
               ...
    示例：

        [ 1 -5 3]        [-8 6  1]         [(1*-8)+(-5*7)+(3*2) (1*6)+(-5*0)+(3*4) (1*1)+(-5*-3)+(3*5)]
    A = [ 0 -2 6]    B = [07 0 -3]    AB=     [(0*-8)+(-2*7)+(6*2) (0*6)+(-2*0)+(6*4) (0*1)+(-2*-3)+(6*5)]
        [ 7 2 -4]        [02 4  5]         [(7*-8)+(2*7)+(-4*2) (7*6)+(2*0)+(-4*4) (7*1)+(2*-3)+(-4*5)]
----------------------------------------------------------------------------------------
    9.向量与矩阵的乘法,DirectX使用行向量,OpenGL使用列向量

    向量V        乘以矩阵          M
                        [m11 m12 m13]
    [x y z]           *    [m21 m22 m23] =[xm11+ym21+zm31 xm12+ym22+zm32 xm13+ym23+zm33]
                        [m31 m32 m33]
----------------------------------------------------------------------------------------
    10.旋转矩阵
----------------------------------------------------------------------------------------
             [ 1   0   0   ]
    Rx(θ)=     [ 0 cosθ  sinθ]
             [ 0 -sinθ cosθ]
----------------------------------------------------------------------------------------
             [ cosθ  0  -sinθ ]
    Ry(θ)=     [ 0     1       0  ]
             [ sinθ  0   cosθ ]
----------------------------------------------------------------------------------------
             [ cosθ  sinθ  0  ]
    Rz(θ)=     [-sinθ  cosθ  0  ]
             [ 0     0     1  ]
----------------------------------------------------------------------------------------
11.正交矩阵：矩阵*矩阵的转置=单位矩阵,则此矩阵称为正交矩阵
意义：<如果能判定一个矩阵为正交矩阵,则计算矩阵的逆可以使用矩阵的转置替代,矩阵转置效率高于直接计算矩阵的逆>
由以下公式：
M*M┯=I
M*M^-1=I
可以推导出：正交矩阵的转置等于正交矩阵的逆
M┯=M^-1
检测正交矩阵公式：
m11m11 + m12m12 + m13m13 = 1
m11m21 + m12m22 + m13m23 = 0
m11m31 + m12m32 + m13m33 = 0

m21m11 + m22m12 + m23m13 = 0
m21m21 + m22m22 + m23m23 = 1
m21m31 + m22m32 + m23m33 = 0

m31m11 + m32m12 + m33m13 = 0
m31m21 + m32m22 + m33m23 = 0
m31m31 + m32m32 + m33m33 = 1
----------------------------------------------------------------------------------------
12. 4*4齐次矩阵

----------------------------------------------------------------------------------------
13. 欧拉角
 用三个旋转角分别表示3D空间中的方位和旋转,三次旋转形成三个角,绕垂直旋转轴旋转可以是任意轴,任意旋转次序

 1.heading角 也称为yaw角,绕Y轴(垂直轴)旋转
 2.pitch角 ,绕X轴旋转
 3.bank角  也称为roll角,绕Z轴旋转
----------------------------------------------------------------------------------------

*/

// 定义矩阵的行和列
#define MATRIX_ROW_COUNT      3
#define MATRIX_COL_COUNT      3

#define MATRIX_TRANSLATION_ROW_COUNT      4
#define MATRIX_TRANSLATION_COL_COUNT      4

/*
    描述3*3的矩阵
*/
class EulerAngle;
class MatrixInformation
{
public:
    // 表示矩阵数据的下标
    enum  MATRIX_DATA_INDEX {
        INDEX0 = 000,
        INDEX1 = 001,
        INDEX2 = 002
    };
protected:
    // 矩阵数据定义
    double(*pNormalMatrixData)[MATRIX_TRANSLATION_COL_COUNT] = NULL;
    VOID InitializationMatrixData() {
        pNormalMatrixData = new double[MATRIX_TRANSLATION_ROW_COUNT][MATRIX_TRANSLATION_COL_COUNT];
    }
private:
    // 欧拉角
    // EulerAngle eulerAngle;
public:
    MatrixInformation();
    ~MatrixInformation();
    MatrixInformation(double data[MATRIX_ROW_COUNT][MATRIX_COL_COUNT]);
    // 打印矩阵数据
    VOID ShowMatrixInformation();
    // 清空矩阵数据
    VOID ZeroMatrixData();
    // 设置矩阵某一行的数据
    VOID SetMatrixRowData(MATRIX_DATA_INDEX rowIndex, double rowData[3]);
    // 设置矩阵某一列的数据
    VOID SetMatrixColData(MATRIX_DATA_INDEX colIndex, double rowData[3]);
    // 设置数据打印格式
    VOID SetCoutWidth(int width = 9);
    // 矩阵数据转换成二维数组
    VOID GetMatrixData(double data[MATRIX_ROW_COUNT][MATRIX_COL_COUNT]);
    // 填充数组的数据到矩阵中
    VOID SetMatrixData(double data[MATRIX_ROW_COUNT][MATRIX_COL_COUNT]);

    // 旋转矩阵
    VOID RotationMatrix(ROTATE_TYPE type, double angle);
    // 缩放矩阵
    VOID SaclingMatrix(double x, double y, double z);
    VOID SaclingMatrix(VectorInformation& vectorInformation);
    // 投影矩阵
    VOID ProjectionMatrix(VectorInformation& vectorInformation);
    VOID ProjectionMatrix(double x, double y, double z);
    // xyz轴的矩阵镜像
    VOID MatrixImageXYZ(ROTATE_TYPE type);
    // 任意平面的矩阵镜像
    VOID ArbitraryMatrixImage(VectorInformation& vectorInformation);
    // 矩阵切变,参数s和t代表系数
    VOID MatrixShear(ROTATE_TYPE ShearType, double s, double t);
    // 矩阵的行列式
    DOUBLE DeterminantMatrix();
    // 转换当前矩阵为单位矩阵
    VOID ConvertToIdentityMatrix();
    // 转换指定的矩阵数据为单位矩阵
    VOID ConvertSpecificArrayToIdentityMatrix(double** data);
    // 惯性坐标系转换成物体坐标系
    VectorInformation InertialToObject(VectorInformation&);
    // 物体坐标系转换成惯性坐标系
    VectorInformation ObjectToInertial(VectorInformation&);
    // 使用欧拉角旋转矩阵
    VOID SetEulerAngle(EulerAngle& eulerAngle);
};

// 转置矩阵
MatrixInformation MatrixTranspose(MatrixInformation& matrixInfo);
// 矩阵与矩阵相乘
MatrixInformation operator*(MatrixInformation& matrixInfo1, MatrixInformation& matrixInfo2);
// 向量与矩阵相乘
VectorInformation operator*(VectorInformation& vectorInfo, MatrixInformation& matrixInfo);
// 计算矩阵的逆
MatrixInformation InverseOfMatrix(MatrixInformation& matrixInfor);
// 矩阵与矩阵相乘
MatrixInformation MatrixMultiply(MatrixInformation& matrixInfo1, MatrixInformation& matrixInfo2);
// 向量与矩阵相乘
VectorInformation VectorMatrixMultiply(VectorInformation& vectorInfo, MatrixInformation& matrixInfo);
#endif // !__MATRIX_INFORMATION_CLASS_DEFINE__